
	/************************************************************************************************

		@API
		Factory: Class

		Methods:
			c		Class			(cid, data)
			b		isClassOf	(obj)
			s		toString	()

		Keyword data:
			exposes:			jsl.Interface | jsl.Interface[]
			inherits:			jsl.Class 		| jsl.Class[]
			initializer:	fn

		Note:
			multiple inheritance: priority level assigned from left(high) to right(low)
			static data:					$

	************************************************************************************************/

	//-------------------------------------------------------------------------------
	jsl.Class = function(cid, data) {
		try {
			var cx, ids, id, l, a, b, t, cname, cn, cls, ifs, obj, f, c, nid, dt

			//!
			if(arguments.length !== 2)	throw jsl.ParamError()
			jsl.validate(cid	, "qid"	, "cid")
			jsl.validate(data	, "o"		, "data")
			if(jsl.Class.__dt[cid])	throw jsl.ParamError("AlreadyDefined:cid")//!

			//1-location search
			//-------------------------------------------------------------------------------
			cx = jsl.__go
			if(cid.indexOf(".") !== -1) {

				ids	= cid.split(".")
				l		= ids.length - 1

				for(a = 0; a < l; a++) {
					id = ids[a]//!
					if(!id) throw jsl.ParamError("BadValue:cid")//!

					cx 	= cx[id]//!
					t 	= typeof cx
					if(t !== "object" && t !== "function")	throw jsl.ParamError("BadValue:cid")
					if(!cx) 																throw jsl.ParamError("BadValue:cid")//!
				}
			}

			//2-data checks
			//-------------------------------------------------------------------------------
			cname	= cid.match(/[^\.]+$/)[0]
			cn 		= data[cname]

			//!
			if(cn && typeof cn !== "function")
				throw jsl.ParamError("BadType:data." + cname + ":function")//!

			if(data.inherits != null) {

				cls = jsl.isArrayLike(data.inherits) ? data.inherits : [ data.inherits ]//!
				if(!cls.length)	throw jsl.ParamError("EmptyArray:data.inherits")//!

				//!
				for(a = 0, l = cls.length; a < l; a++) {
					if(cls[a] == null)				throw jsl.ParamError("NullValue:data.inherits[" + a + "]")
					if(!jsl.isClass(cls[a]))	throw jsl.ParamError("BadType", [ "data.inherits[" + a + "]", "jsl.Class" ])
				}//!
			}

			if(data.exposes != null) {

				ifs = jsl.isArrayLike(data.exposes) ? data.exposes : [ data.exposes ]//!
				if(!ifs.length)	throw jsl.ParamError("EmptyArray:data.exposes")//!

				//!
				for(a = 0, l = ifs.length; a < l; a++) {
					if(ifs[a] == null)						throw jsl.ParamError("NullValue:data.exposes[" + a + "]")
					if(!jsl.isInterface(ifs[a]))	throw jsl.ParamError("BadType", [ "data.exposes[" + a + "]", "jsl.Interface" ])
				}//!
			}

			//3-class creation
			//-------------------------------------------------------------------------------
			c = function() {
				try {
					var obj, cl, rbj

					cl = arguments.callee

					if(this instanceof cl && !this.__create) {
						this.constructor	= cl
						this.__proto 			= cl.prototype
						this.__create			= true

						if(cn) obj = cn.apply(this, arguments)
						if(obj == null) obj = this
					}
					else {
						jsl.__f.prototype = cl.prototype
						obj 						= new jsl.__f
						obj.constructor	= cl
						obj.__proto 		= cl.prototype
						obj.__create		= true
						if(cn) rbj = cn.apply(obj, arguments)
						if(rbj != null) obj = rbj
					}

					return obj
				}
				catch(e) {
					jsl.throwError(e, cid, arguments)
				}
			}

			//4-inheritance
			//-------------------------------------------------------------------------------
			if(cls && cls.length) {

				//constructor bypass
				jsl.__f.prototype = cls[0].prototype
				c.prototype = new jsl.__f
				c.prototype.toString = c.toString = jsl.Class.toString

				for(a = cls.length - 1; a >= 0; a--) {
					for(b in cls[a])						c[b] = cls[a][b]
					for(b in cls[a].prototype)	c.prototype[b] = cls[a].prototype[b]

					//@sys: Explorer 8 - the method toString is not enumerated in the for/in loop also if is set to a custom function
					if(cls[a].hasOwnProperty("toString")) 					c.toString 	= cls[a].toString
					if(cls[a].hasOwnProperty("valueOf")) 						c.valueOf 	= cls[a].valueOf
					if(cls[a].prototype.hasOwnProperty("toString")) c.prototype.toString 	= cls[a].prototype.toString
					if(cls[a].prototype.hasOwnProperty("valueOf")) 	c.prototype.valueOf 	= cls[a].prototype.valueOf
				}
			}
			else {
				c.prototype = {}
				c.prototype.toString = c.toString = jsl.Class.toString
				jsl.Object(c.prototype)
			}

			data[cname] = cn || jsl.__f
			for(id in data)
				if(id !== "inherits" && id !== "exposed") {

					if(id.charAt(0) !== "$") {
						obj = c.prototype
						nid = id
					}
					else {
						obj = c
						nid = id.slice(1)
					}

					//1-data
					if(typeof data[id] !== "function")
						obj[nid] = data[id]

					//2-function
					else {

						if(jsl.__dbg) {
							f = function() {
								try {
									var oname
									return arguments.callee.__f.apply(this, arguments)
								}
								catch(e) {
									oname	= jsl.Object.oid(this) || jsl.__mlng_object_name(this)
									jsl.throwError(e, oname + "." + arguments.callee.__name, arguments)
								}
							}

							f.__f			= data[id]
							f.__name	= nid
						}
						else
							f = data[id]

						obj[nid] = f
					}
				}

			//@sys: Explorer 8 - the method toString is not enumerated in the for/in loop also if is set to a custom function
			if(data.hasOwnProperty("toString")) c.prototype.toString = data.toString
			if(data.$toString) 									c.toString = data.$toString

			if(data.hasOwnProperty("valueOf")) 	c.prototype.valueOf = data.valueOf
			if(data.$valueOf) 									c.valueOf = data.$valueOf

			//!
			if(ifs)
				for(a = 0, l = ifs.length; a < l; a++) {

					dt = ifs[a].methods()
					for(b = 0; b < dt.length; b++) {

						id = dt[b]
						if(id.charAt(0) === "$") {
							if(typeof c[id.slice(1)] !== "function")
								throw jsl.ParamError("InterfaceNotImplemented", [ cid, id ])
						}
						else
							if(typeof obj[id] !== "function")
								throw jsl.ParamError("InterfaceNotImplemented", [ cid, id ])
					}
				}//!

			c.__name 			= cid
			c.__cid				= cid
			c.__signature	= jsl.__signatures["jsl.Class"]
			c.isClassOf		= jsl.Class.isClassOf

      c.prototype.__name 					= cid
			c.prototype.__sid						= cid
			c.prototype.__proto					= cls && cls.length ? cls[0].prototype 	: jsl.Object.prototype
			c.prototype.constructor			= cls && cls.length ? cls[0] : jsl.Object
			c.prototype["__cid_" + cid]	= true

			delete c.initializer
			delete c.prototype.initializer

			if(data.initializer != null) {//!
				jsl.validate(data.initializer, "f", "data.initializer")//!
				try 			{ data.initializer.call(c) }
				catch(e) 	{ throw jsl.ScriptError("BadScript", [ cid + ".initializer()"], e) }
			}

			jsl.Class.__dt[cid] = cx[cname] = c
			return c
		}
		catch(e) {
      jsl.throwError(e, jsl, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Class.prototype = jsl.Object()
	//-------------------------------------------------------------------------------
	jsl.Class.__name 		= "Class"
	jsl.Class.__dt 			=	[]
  //-------------------------------------------------------------------------------
	jsl.Class.isClassOf = function(obj) {
		try {//!
			if(arguments.length !== 1)	throw jsl.ParamError()//!
			return obj && !!obj["__cid_" + this.__cid]
		}
		catch(e) {
			jsl.throwError(e, this, arguments)
		}
	}
  //-------------------------------------------------------------------------------
	jsl.Class.toString = function() {
		return this.__name
	}
